package com.treetao.union.db.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.treetao.union.core.redis.RedisService;
import com.treetao.union.db.Const;
import com.treetao.union.db.Const.OrderQueryType;
import com.treetao.union.db.Const.OrderRecord;
import com.treetao.union.db.Const.OrderStatus;
import com.treetao.union.db.mapper.MallOrderMapper;
import com.treetao.union.db.model.MallOrder;
import com.treetao.union.db.model.MallOrderDetail;
import com.treetao.union.db.model.MallOrderExpress;
import com.treetao.union.db.model.MallPSku;
import com.treetao.union.db.service.MallOrderDetailService;
import com.treetao.union.db.service.MallOrderExpressService;
import com.treetao.union.db.service.MallOrderPayrecordService;
import com.treetao.union.db.service.MallOrderRecordService;
import com.treetao.union.db.service.MallOrderService;
import com.treetao.union.db.service.MallPSkuService;
import com.treetao.union.db.service.MallSkillService;

/**
 * <p>
 * 订单主表 服务实现类
 * </p>
 *
 * @author Dev.M
 * @since 2020-04-11
 */
@Service
public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder> implements MallOrderService {
	@Autowired
	private MallOrderDetailService mallOrderDetailService;
	@Autowired
	private MallOrderRecordService mallOrderRecordService;
	@Autowired
	private MallOrderPayrecordService mallOrderPayrecordService;
	@Autowired
	private MallOrderExpressService orderExpressService;
	@Autowired
	private MallPSkuService mallPSkuService;
	@Autowired
	private MallSkillService mallSkillService;
	@Autowired
	private RedisService redisService;
	
	@Transactional(rollbackFor = Exception.class)
	@Override
	public boolean createOrder(MallOrder order, List<MallOrderDetail> details) {
		boolean flag = save(order);
		boolean flag2 = false;
		boolean flag3 = false;
		boolean flag4 = false;
		if (flag) {
			flag2 = mallOrderDetailService.saveBatch(details);
			flag3 = mallOrderRecordService.save(order.getOrderno(), Const.OrderRecord.CREATE);
			flag4 = orderExpressService.save(order.getExpress());
		}
		return flag && flag2 && flag3 && flag4;
	}

	@Transactional
	@Override
	public boolean send(Long orderno, String companyNo, String expressNo) {
		MallOrderExpress express = orderExpressService.getOrderExpress(orderno);
		if (express != null) {
			express.setCompanyNo(companyNo);
			express.setExpressNo(expressNo);
		}
		boolean flag1 = orderExpressService.updateById(express);
		boolean flag2 = changeOrderStatus(orderno, OrderStatus.SEND, OrderRecord.SEND);
		return flag1 && flag2;
	}

	@Override
	public MallOrder getMallOrderDetail(Long orderno, Boolean refExpress) {
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.eq("orderno", orderno);
		MallOrder order = getOne(q);
		if (order == null)
			return null;

		// 关联SKU
		QueryWrapper<MallOrderDetail> qDetail = new QueryWrapper<MallOrderDetail>();
		qDetail.eq("orderno", orderno);
		List<MallOrderDetail> details = mallOrderDetailService.list(qDetail);
		order.setDetails(details);

		if (refExpress) {
			// 关联收货及物流信息
			QueryWrapper<MallOrderExpress> qExpress = new QueryWrapper<MallOrderExpress>();
			qExpress.eq("orderno", orderno);
			MallOrderExpress express = orderExpressService.getOne(qExpress);
			order.setExpress(express);
		}

		order.setDelFlag(null);

		return order;
	}

	@Override
	public List<MallOrder> getMallOrderList(Long userId, Long curpage, Long size, String type) {
		IPage<MallOrder> ipage = new Page<MallOrder>(curpage, size);
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		if (OrderQueryType.PAY.equals(type)) { // 待支付
			q.eq("status", OrderStatus.CREATE.getValue());
		} else if (OrderQueryType.REVEIVE.equals(type)) { // 待收货
			q.eq("status", OrderStatus.SEND.getValue());
		} else if (OrderQueryType.COMMENT.equals(type)) { // 待评价
			q.in("status", OrderStatus.RECEIVED_USER.getValue(), OrderStatus.RECEIVED_USER.getValue());
		} else if (OrderQueryType.FINISH.equals(type)) { // 已完成
			q.in("status", OrderStatus.CANCLE_SYSTEM.getValue(), OrderStatus.CANCLE_USER.getValue(),
					OrderStatus.COMMENTED.getValue(), OrderStatus.REFUND.getValue());
		}
		q.eq("user_id", userId);
		q.orderByDesc("create_time");
		IPage<MallOrder> pages = page(ipage, q);
		List<MallOrder> list = pages.getRecords();
		if (list != null) {
			for (MallOrder order : list) {
				QueryWrapper<MallOrderDetail> qDetail = new QueryWrapper<MallOrderDetail>();
				qDetail.eq("orderno", order.getOrderno());
				List<MallOrderDetail> details = mallOrderDetailService.list(qDetail);
				order.setDetails(details);

				order.setDelFlag(null);
			}
		}

		return list;
	}

	@Override
	public MallOrder getMallOrder(Long orderno) {
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.eq("orderno", orderno);
		return getOne(q);
	}

	@Transactional
	@Override
	public boolean changeOrderStatus(Long orderno, OrderStatus status, String opRecordContent) {
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.eq("orderno", orderno);
		MallOrder order = getOne(q);
		if (order != null) {
			if (status.getValue() == OrderStatus.SEND.getValue()) {// 如果是发货，则填充发货时间
				order.setSendTime(new Date());
			} else if (status.getValue() == OrderStatus.PAYED.getValue()){//如果是支付回调，更新SKU销量
				List<MallOrderDetail> details = mallOrderDetailService.getDetails(orderno);
				if(details!=null) {
					for(MallOrderDetail od : details) {
						long skuId = od.getSkuId();
						int num = od.getNum();
						MallPSku sku = mallPSkuService.getById(skuId);
						int saledNum = sku.getSaledNum()==null?0:sku.getSaledNum();
						saledNum = saledNum + num;
						sku.setSaledNum(saledNum);
						mallPSkuService.updateById(sku);
						
						if(status.getValue() == OrderStatus.CANCLE_USER.getValue() || 
								status.getValue() == OrderStatus.CANCLE_SYSTEM.getValue()) {
							//订单取消，如果订单中的产品还在秒杀活动中，还原库存
							boolean exist = mallSkillService.existSkilling(skuId);
							if(exist) {
								//还原库存
								redisService.hincr(Const.skillRedisKey, String.valueOf(skuId), 1);
							}
						}
					}
				}
			}
			order.setStatus(status.getValue());
			boolean flag = updateById(order);
			if (flag && opRecordContent != null) {
				return mallOrderRecordService.save(orderno, opRecordContent);
			} else {
				return flag;
			}
		}
		return false;
	}

	@Transactional
	@Override
	public boolean payNotifyedWeixin(Long orderno, Double price, String xml) {
		boolean flag = changeOrderStatus(orderno, OrderStatus.PAYED, null);
		boolean flag2 = mallOrderPayrecordService.savePayWeixin(orderno, price, xml);
		return flag && flag2;
	}

	@Override
	public List<MallOrder> getOrderListAtferCreate(int hour) {
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.eq("status", OrderStatus.CREATE.getValue());
		q.le("date_add(create_time, interval "+hour+" hour)", new Date());

		return list(q);
	}

	@Override
	public List<MallOrder> getOrderListAtferSend(int day) {
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.eq("status", OrderStatus.SEND.getValue());
		q.le("date_add(send_time, interval "+day+" DAY)", new Date());

		return list(q);
	}

	/**
	 * 有效的订单状态（已支付，未取消）
	 * 
	 * @return
	 */
	private Object[] getValidStatus() {
		return new Object[] { OrderStatus.PREPAYED.getValue(), OrderStatus.PAYED.getValue(),
				OrderStatus.SEND.getValue(), OrderStatus.RECEIVED_SYSTEM.getValue(),
				OrderStatus.RECEIVED_USER.getValue() };
	}

	@Override
	public int getTodayOrderNum() {
		// 今日订单数
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.in("status", getValidStatus());
		q.eq("to_days(create_time)", "to_days(now())");// 今日
		return count(q);
	}

	@Override
	public int getMonthOrderNum() {
		// 本月订单数
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.in("status", getValidStatus());
		q.eq("DATE_FORMAT(create_time,'%Y%m')", "DATE_FORMAT( CURDATE() ,'%Y%m' )");
		return count(q);
	}

	@Override
	public double getTodayMoney() {
		// 今日销售额
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.in("status", getValidStatus());
		q.eq("to_days(create_time)", "to_days(now())");
		q.select("SUM(price_real) price");
		Map<String, Object> map = getMap(q);
		if(map==null) return 0d;
		return (double) map.get("price");
	}

	@Override
	public double getMonthMoney() {
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.in("status", getValidStatus());
		q.eq("DATE_FORMAT(create_time,'%Y%m')", "DATE_FORMAT( CURDATE() ,'%Y%m' )");
		q.select("SUM(price_real) price");
		Map<String, Object> map = getMap(q);
		if(map==null) return 0d;
		return (double) map.get("price");
	}

	@Override
	public double getMonthMoney(String monthStr) {
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.in("status", getValidStatus());
		q.eq("DATE_FORMAT(create_time,'%Y-%m')", monthStr);
		q.select("SUM(price_real) price");
		Map<String, Object> map = getMap(q);
		if(map==null) return 0d;
		return (double) map.get("price");
	}

	@Override
	public double getDayMoney(String dayStr) {
		QueryWrapper<MallOrder> q = new QueryWrapper<MallOrder>();
		q.in("status", getValidStatus());
		q.eq("DATE_FORMAT(create_time,'%Y-%m-%d')", dayStr);
		q.select("SUM(price_real) price");
		Map<String, Object> map = getMap(q);
		if(map==null) return 0d;
		return (double) map.get("price");
	}

}
